package cn.tuling.http;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
import org.springframework.web.client.*;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Random;

public class MyRestTemplate extends RestTemplate {
    private Logger log = LoggerFactory.getLogger(MyRestTemplate.class);

    private DiscoveryClient discoveryClient;

    public MyRestTemplate(DiscoveryClient discoveryClient) {
        this.discoveryClient = discoveryClient;
    }

    @Override
    protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException {
        Assert.notNull(url, "URI is required");
        Assert.notNull(method, "HttpMethod is required");
        ClientHttpResponse response = null;
        try {
            log.info("请求的url路径为{}", url);
            url = replaceUrl(url);
            log.info("替换后的url路径为{}", url);

            ClientHttpRequest request = createRequest(url, method);
            if (requestCallback != null) {
                requestCallback.doWithRequest(request);
            }
            response = request.execute();
            handleResponse(url, method, response);
            return (responseExtractor != null ? responseExtractor.extractData(response) : null);
        } catch (IOException ex) {
            String resource = url.toString();
            String query = url.getRawQuery();
            resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
            throw new ResourceAccessException("I/O error on " + method.name() +
                    " request for \"" + resource + "\": " + ex.getMessage(), ex);
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    private URI replaceUrl(URI url) {
        String serviceName = url.getHost();
        log.info("调用微服务的名称：{}", serviceName);

        String path = url.getPath();
        log.info("请求Path: {}", path);

        List<ServiceInstance> serviceList = discoveryClient.getInstances(serviceName);
        if (serviceList.isEmpty()) {
            throw new RuntimeException("没有可用的服务实例列表：" + serviceName);
        }


        String serviceIp = chooseServiceIp(serviceList);

        String newUrl = serviceIp + path;
        try {
            return new URI(newUrl);
        } catch (URISyntaxException e) {
            log.info("根据sourceUrl  {} 构建URI异常", url);
        }
        return url;
    }

    private String chooseServiceIp(List<ServiceInstance> serviceList) {
        Random random = new Random();
        int index = random.nextInt(serviceList.size());
        String uri = serviceList.get(index).getUri().toString();
        log.info("随机选取的服务IP：{}", uri);
        return uri;
    }
}
